//! 彩色格式化器模块
//!
//! 提供带 ANSI 颜色的日志格式化器实现。
//!
//! ## 颜色方案
//!
//! | 级别 | 颜色 |
//! |------|------|
//! | TRACE | 灰色 (bright_black) |
//! | DEBUG | 蓝色 (blue) |
//! | INFO | 绿色 (green) |
//! | WARN | 黄色 (yellow) |
//! | ERROR | 红色 (red) |
//! | FATAL | 红色加粗 (red + bold) |
//!
//! ## Feature Flag
//!
//! 此模块需要启用 `color` feature：
//!
//! ```toml
//! [dependencies]
//! log4r = { version = "0.8", features = ["color"] }
//! ```

use std::io::IsTerminal;
use std::sync::OnceLock;

/// 缓存的终端颜色检测结果
///
/// 使用 OnceLock 实现线程安全的单次初始化，避免重复系统调用开销。
/// 缓存的是终端环境检测结果（NO_COLOR、TERM、is_terminal），不包含配置状态。
static TERMINAL_COLOR_SUPPORT: OnceLock<bool> = OnceLock::new();

use owo_colors::OwoColorize;
use time::format_description::FormatItem;
use time::macros::format_description;

use crate::event::LogEvent;
use crate::formatter::Formatter;
use crate::level::Level;

/// 时间格式描述：YYYY-MM-DD HH:MM:SS.mmm
const TIME_FORMAT: &[FormatItem<'static>] =
    format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:3]");

/// 时间格式化失败时的占位符
const TIME_FALLBACK: &str = "????-??-?? ??:??:??.???";

/// 彩色格式化器
///
/// 为不同日志级别应用不同颜色，提升日志可读性。
///
/// ## 输出格式
///
/// `{time} [{level}] {target}: {message}`
///
/// - 时间戳：暗灰色 (bright_black)
/// - 级别：按级别着色
/// - 模块路径：青色 (cyan)
/// - 消息：默认色
///
/// ## 示例
///
/// ```rust,ignore
/// use log4r::formatter::{Formatter, ColoredFormatter};
/// use log4r::{Level, LogEvent};
///
/// let formatter = ColoredFormatter::new(true);
/// let event = LogEvent::new(Level::Info, "my_app", "Hello!");
/// let output = formatter.format(&event);
/// // 输出带 ANSI 颜色转义码
/// ```
#[derive(Debug, Clone)]
pub struct ColoredFormatter {
    /// 是否启用彩色输出
    enabled: bool,
}

// 编译时断言：验证 ColoredFormatter 实现 Send + Sync
const _: () = {
    const fn assert_send_sync<T: Send + Sync>() {}
    assert_send_sync::<ColoredFormatter>();
};

impl ColoredFormatter {
    /// 创建新的彩色格式化器
    ///
    /// # Arguments
    ///
    /// * `enabled` - 是否启用彩色输出
    ///
    /// # 示例
    ///
    /// ```rust,ignore
    /// use log4r::formatter::ColoredFormatter;
    ///
    /// // 启用彩色
    /// let formatter = ColoredFormatter::new(true);
    ///
    /// // 禁用彩色（输出与 TextFormatter 相同）
    /// let formatter = ColoredFormatter::new(false);
    /// ```
    #[inline]
    pub fn new(enabled: bool) -> Self {
        Self { enabled }
    }

    /// 格式化时间戳
    #[inline]
    fn format_timestamp(&self, event: &LogEvent) -> String {
        let time_str = event.timestamp.format(TIME_FORMAT).unwrap_or_else(|_| {
            event
                .timestamp
                .to_offset(time::UtcOffset::UTC)
                .format(TIME_FORMAT)
                .unwrap_or_else(|_| TIME_FALLBACK.to_string())
        });

        if self.enabled {
            time_str.bright_black().to_string()
        } else {
            time_str
        }
    }

    /// 根据级别获取颜色化的级别字符串
    ///
    /// 颜色方案：
    /// - TRACE: 灰色 (bright_black)
    /// - DEBUG: 蓝色 (blue)
    /// - INFO: 绿色 (green)
    /// - WARN: 黄色 (yellow)
    /// - ERROR: 红色 (red)
    /// - FATAL: 红色加粗 (red + bold)
    #[inline]
    fn colorize_level(&self, level: Level) -> String {
        let level_str = format!("{:<5}", level.as_str());

        if !self.enabled {
            return level_str;
        }

        match level {
            Level::Trace => level_str.bright_black().to_string(),
            Level::Debug => level_str.blue().to_string(),
            Level::Info => level_str.green().to_string(),
            Level::Warn => level_str.yellow().to_string(),
            Level::Error => level_str.red().to_string(),
            Level::Fatal => level_str.red().bold().to_string(),
        }
    }

    /// 格式化模块路径
    #[inline]
    fn format_target(&self, target: &str) -> String {
        if self.enabled {
            target.cyan().to_string()
        } else {
            target.to_string()
        }
    }
}

impl Default for ColoredFormatter {
    fn default() -> Self {
        Self::new(true)
    }
}

impl Formatter for ColoredFormatter {
    /// 将日志事件格式化为带颜色的字符串
    ///
    /// 输出格式：`{time} [{level}] {target}: {message}`
    fn format(&self, event: &LogEvent) -> String {
        let timestamp = self.format_timestamp(event);
        let level = self.colorize_level(event.level);
        let target = self.format_target(&event.target);

        format!("{} [{}] {}: {}", timestamp, level, target, event.message)
    }
}

/// 检测终端是否支持彩色输出（内部函数，不缓存）
///
/// 检测顺序：
/// 1. NO_COLOR 环境变量存在 → false
/// 2. TERM=dumb → false
/// 3. stdout 不是 TTY → false
/// 4. 其他情况 → true
///
/// # 参考
///
/// - [NO_COLOR 标准](https://no-color.org/)
fn detect_terminal_color_support() -> bool {
    // 1. NO_COLOR 环境变量 (https://no-color.org/)
    // 遵循标准：环境变量存在即禁用颜色，不检查值
    if std::env::var("NO_COLOR").is_ok() {
        return false;
    }

    // 2. TERM=dumb 检测
    if std::env::var("TERM").map(|t| t == "dumb").unwrap_or(false) {
        return false;
    }

    // 3. 检测 stdout 是否为终端
    std::io::stdout().is_terminal()
}

/// 检测是否应该启用彩色输出
///
/// 检测顺序：
/// 1. 配置显式禁用 → false
/// 2. NO_COLOR 环境变量存在 → false
/// 3. TERM=dumb → false
/// 4. stdout 不是 TTY → false
/// 5. 其他情况 → true
///
/// # Arguments
///
/// * `config_enabled` - 配置是否启用彩色
///
/// # 示例
///
/// ```rust,ignore
/// use log4r::formatter::should_colorize;
///
/// // 检测是否应该启用彩色
/// let use_color = should_colorize(true);
/// ```
///
/// # 参考
///
/// - [NO_COLOR 标准](https://no-color.org/)
pub fn should_colorize(config_enabled: bool) -> bool {
    // 配置显式禁用时直接返回 false，不使用缓存
    if !config_enabled {
        return false;
    }

    // 使用缓存的终端检测结果
    *TERMINAL_COLOR_SUPPORT.get_or_init(detect_terminal_color_support)
}

/// 获取缓存的终端彩色支持检测结果
///
/// 此函数返回缓存的终端环境检测结果，首次调用时执行检测并缓存。
/// 与 `should_colorize` 不同，此函数不考虑配置状态，仅返回终端能力。
///
/// 检测内容：
/// - NO_COLOR 环境变量
/// - TERM=dumb 环境变量
/// - stdout 是否为 TTY
///
/// # 返回值
///
/// - `true` - 终端支持彩色输出
/// - `false` - 终端不支持彩色输出
///
/// # 示例
///
/// ```rust,ignore
/// use log4r::formatter::cached_terminal_color_support;
///
/// // 获取缓存的终端检测结果
/// let terminal_supports_color = cached_terminal_color_support();
/// ```
///
/// # 性能
///
/// 首次调用执行系统调用检测，后续调用直接返回缓存值 (O(1))。
pub fn cached_terminal_color_support() -> bool {
    *TERMINAL_COLOR_SUPPORT.get_or_init(detect_terminal_color_support)
}

#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::expect_used)]
mod tests {
    use super::*;

    // =========================================================================
    // Task 2: ColoredFormatter 结构体测试
    // =========================================================================

    // UT-9.1-001: 测试 ColoredFormatter::new() 创建
    #[test]
    fn test_colored_formatter_new() {
        // GIVEN/WHEN: 创建启用彩色的格式化器
        let formatter = ColoredFormatter::new(true);

        // THEN: enabled 应为 true
        assert!(formatter.enabled);
    }

    // UT-9.1-002: 测试 ColoredFormatter::new(false) 创建
    #[test]
    fn test_colored_formatter_new_disabled() {
        // GIVEN/WHEN: 创建禁用彩色的格式化器
        let formatter = ColoredFormatter::new(false);

        // THEN: enabled 应为 false
        assert!(!formatter.enabled);
    }

    // UT-9.1-003: 测试 Default trait
    #[test]
    fn test_colored_formatter_default() {
        // GIVEN/WHEN: 使用 default() 创建
        let formatter = ColoredFormatter::default();

        // THEN: 默认应启用彩色
        assert!(formatter.enabled);
    }

    // UT-9.1-004: 测试 Clone trait
    #[test]
    fn test_colored_formatter_clone() {
        // GIVEN: 创建格式化器
        let formatter = ColoredFormatter::new(true);

        // WHEN: 克隆
        let cloned = formatter.clone();

        // THEN: 克隆应相同
        assert_eq!(formatter.enabled, cloned.enabled);
    }

    // UT-9.1-005: 编译时验证 Send + Sync
    #[test]
    fn test_colored_formatter_send_sync() {
        fn assert_send_sync<T: Send + Sync>() {}
        assert_send_sync::<ColoredFormatter>();
    }

    // =========================================================================
    // Task 3: 级别颜色映射测试
    // =========================================================================

    // UT-9.1-006: TRACE 级别输出灰色
    #[test]
    fn test_colorize_level_trace() {
        let formatter = ColoredFormatter::new(true);
        let output = formatter.colorize_level(Level::Trace);

        // bright_black ANSI: \x1b[90m
        assert!(
            output.contains("\x1b[90m"),
            "TRACE 应使用 bright_black，实际: {}",
            output
        );
    }

    // UT-9.1-007: DEBUG 级别输出蓝色
    #[test]
    fn test_colorize_level_debug() {
        let formatter = ColoredFormatter::new(true);
        let output = formatter.colorize_level(Level::Debug);

        // blue ANSI: \x1b[34m
        assert!(
            output.contains("\x1b[34m"),
            "DEBUG 应使用 blue，实际: {}",
            output
        );
    }

    // UT-9.1-008: INFO 级别输出绿色
    #[test]
    fn test_colorize_level_info() {
        let formatter = ColoredFormatter::new(true);
        let output = formatter.colorize_level(Level::Info);

        // green ANSI: \x1b[32m
        assert!(
            output.contains("\x1b[32m"),
            "INFO 应使用 green，实际: {}",
            output
        );
    }

    // UT-9.1-009: WARN 级别输出黄色
    #[test]
    fn test_colorize_level_warn() {
        let formatter = ColoredFormatter::new(true);
        let output = formatter.colorize_level(Level::Warn);

        // yellow ANSI: \x1b[33m
        assert!(
            output.contains("\x1b[33m"),
            "WARN 应使用 yellow，实际: {}",
            output
        );
    }

    // UT-9.1-010: ERROR 级别输出红色
    #[test]
    fn test_colorize_level_error() {
        let formatter = ColoredFormatter::new(true);
        let output = formatter.colorize_level(Level::Error);

        // red ANSI: \x1b[31m
        assert!(
            output.contains("\x1b[31m"),
            "ERROR 应使用 red，实际: {}",
            output
        );
    }

    // UT-9.1-011: FATAL 级别输出红色加粗
    #[test]
    fn test_colorize_level_fatal() {
        let formatter = ColoredFormatter::new(true);
        let output = formatter.colorize_level(Level::Fatal);

        // red ANSI: \x1b[31m, bold ANSI: \x1b[1m
        assert!(
            output.contains("\x1b[31m") && output.contains("\x1b[1m"),
            "FATAL 应使用 red + bold，实际: {}",
            output
        );
    }

    // UT-9.1-012: 禁用彩色时无 ANSI 转义码
    #[test]
    fn test_colorize_level_disabled() {
        let formatter = ColoredFormatter::new(false);

        for level in [
            Level::Trace,
            Level::Debug,
            Level::Info,
            Level::Warn,
            Level::Error,
            Level::Fatal,
        ] {
            let output = formatter.colorize_level(level);
            assert!(
                !output.contains("\x1b["),
                "禁用彩色时不应有 ANSI 转义码，级别: {:?}, 输出: {}",
                level,
                output
            );
        }
    }

    // UT-9.1-013: 级别字符串固定宽度 5 字符
    #[test]
    fn test_colorize_level_width() {
        let formatter = ColoredFormatter::new(false);

        for level in [
            Level::Trace,
            Level::Debug,
            Level::Info,
            Level::Warn,
            Level::Error,
            Level::Fatal,
        ] {
            let output = formatter.colorize_level(level);
            assert_eq!(
                output.len(),
                5,
                "级别 {:?} 应为 5 字符，实际: {} ({})",
                level,
                output.len(),
                output
            );
        }
    }

    // =========================================================================
    // Task 4: Formatter trait 实现测试
    // =========================================================================

    // UT-9.1-014: 时间戳使用暗灰色
    #[test]
    fn test_format_timestamp_color() {
        let formatter = ColoredFormatter::new(true);
        let event = LogEvent::new(Level::Info, "test", "message");
        let output = formatter.format(&event);

        // 时间戳应使用 bright_black
        assert!(
            output.contains("\x1b[90m"),
            "时间戳应使用暗灰色，实际: {}",
            output
        );
    }

    // UT-9.1-015: 模块路径使用青色
    #[test]
    fn test_format_target_color() {
        let formatter = ColoredFormatter::new(true);
        let event = LogEvent::new(Level::Info, "my_app::module", "message");
        let output = formatter.format(&event);

        // 模块路径应使用 cyan: \x1b[36m
        assert!(
            output.contains("\x1b[36m"),
            "模块路径应使用青色，实际: {}",
            output
        );
        assert!(output.contains("my_app::module"));
    }

    // UT-9.1-016: 完整格式化输出
    #[test]
    fn test_format_complete_output() {
        let formatter = ColoredFormatter::new(true);
        let event = LogEvent::new(Level::Warn, "test::module", "警告消息");
        let output = formatter.format(&event);

        // 应包含所有部分
        assert!(output.contains("WARN"), "应包含级别");
        assert!(output.contains("test::module"), "应包含模块路径");
        assert!(output.contains("警告消息"), "应包含消息");
        assert!(output.contains("\x1b["), "应包含 ANSI 转义码");
    }

    // UT-9.1-017: 禁用彩色时输出无转义码
    #[test]
    fn test_format_disabled_no_ansi() {
        let formatter = ColoredFormatter::new(false);
        let event = LogEvent::new(Level::Info, "test", "message");
        let output = formatter.format(&event);

        assert!(
            !output.contains("\x1b["),
            "禁用彩色时不应有 ANSI 转义码，实际: {}",
            output
        );
    }

    // UT-9.1-018: 作为 trait object 使用
    #[test]
    fn test_formatter_as_trait_object() {
        let formatter: Box<dyn Formatter> = Box::new(ColoredFormatter::new(true));
        let event = LogEvent::new(Level::Info, "test", "message");
        let output = formatter.format(&event);

        assert!(!output.is_empty());
        assert!(output.contains("INFO"));
    }

    // =========================================================================
    // should_colorize 函数测试
    // =========================================================================

    // UT-9.1-019: 配置禁用时返回 false
    #[test]
    fn test_should_colorize_config_disabled() {
        let result = should_colorize(false);
        assert!(!result, "配置禁用时应返回 false");
    }

    // UT-9.1-020: NO_COLOR 环境变量禁用颜色
    // 注意：由于缓存机制，此测试直接测试内部检测函数
    #[test]
    fn test_should_colorize_no_color_env() {
        std::env::set_var("NO_COLOR", "1");
        let result = detect_terminal_color_support();
        std::env::remove_var("NO_COLOR");

        assert!(!result, "NO_COLOR=1 时应返回 false");
    }

    // UT-9.1-021: TERM=dumb 禁用颜色
    // 注意：由于缓存机制，此测试直接测试内部检测函数
    #[test]
    fn test_should_colorize_term_dumb() {
        std::env::remove_var("NO_COLOR");
        std::env::set_var("TERM", "dumb");
        let result = detect_terminal_color_support();
        std::env::remove_var("TERM");

        assert!(!result, "TERM=dumb 时应返回 false");
    }

    // =========================================================================
    // Story 9.3: 缓存机制测试 (AC-9.3.5)
    // =========================================================================

    // UT-9.3-001: cached_terminal_color_support 函数存在且可调用
    #[test]
    fn test_cached_terminal_color_support_exists() {
        // GIVEN/WHEN: 调用缓存函数
        let result = cached_terminal_color_support();

        // THEN: 应返回布尔值（不 panic）
        let _ = result;
    }

    // UT-9.3-002: 多次调用 cached_terminal_color_support 返回相同结果
    #[test]
    fn test_cached_terminal_color_support_consistent() {
        // GIVEN: 首次调用
        let first_result = cached_terminal_color_support();

        // WHEN: 多次调用
        let second_result = cached_terminal_color_support();
        let third_result = cached_terminal_color_support();

        // THEN: 结果应一致（缓存生效）
        assert_eq!(first_result, second_result, "缓存结果应一致");
        assert_eq!(second_result, third_result, "缓存结果应一致");
    }

    // UT-9.3-003: should_colorize 使用缓存（配置启用时）
    #[test]
    fn test_should_colorize_uses_cache() {
        // GIVEN: 清理环境变量
        std::env::remove_var("NO_COLOR");
        std::env::remove_var("TERM");

        // WHEN: 多次调用 should_colorize(true)
        let first = should_colorize(true);
        let second = should_colorize(true);

        // THEN: 结果应一致
        assert_eq!(first, second, "should_colorize 应使用缓存");
    }

    // UT-9.3-004: 配置禁用时不使用缓存（直接返回 false）
    #[test]
    fn test_should_colorize_config_disabled_no_cache() {
        // GIVEN/WHEN: 配置禁用
        let result = should_colorize(false);

        // THEN: 应直接返回 false，不依赖缓存
        assert!(!result, "配置禁用时应返回 false");
    }

    // UT-9.3-005: 缓存线程安全测试
    #[test]
    fn test_cached_terminal_color_support_thread_safe() {
        use std::sync::Arc;
        use std::thread;

        // GIVEN: 多线程环境
        let results = Arc::new(std::sync::Mutex::new(Vec::new()));
        let mut handles = vec![];

        // WHEN: 多线程并发调用
        for _ in 0..4 {
            let results_clone = Arc::clone(&results);
            let handle = thread::spawn(move || {
                for _ in 0..10 {
                    let result = cached_terminal_color_support();
                    results_clone.lock().unwrap().push(result);
                }
            });
            handles.push(handle);
        }

        // 等待所有线程完成
        for handle in handles {
            handle.join().unwrap();
        }

        // THEN: 所有结果应一致
        let results = results.lock().unwrap();
        let first = results[0];
        for result in results.iter() {
            assert_eq!(*result, first, "多线程调用结果应一致");
        }
    }

    // =========================================================================
    // 边界情况测试
    // =========================================================================

    // UT-9.1-022: 空消息格式化
    #[test]
    fn test_format_empty_message() {
        let formatter = ColoredFormatter::new(true);
        let event = LogEvent::new(Level::Info, "test", "");
        let output = formatter.format(&event);

        assert!(output.contains("INFO"));
        assert!(output.ends_with(": "));
    }

    // UT-9.1-023: 空 target 格式化
    #[test]
    fn test_format_empty_target() {
        let formatter = ColoredFormatter::new(true);
        let event = LogEvent::new(Level::Info, "", "message");
        let output = formatter.format(&event);

        assert!(output.contains("INFO"));
        assert!(output.contains(": message"));
    }

    // UT-9.1-024: Unicode 消息格式化
    #[test]
    fn test_format_unicode_message() {
        let formatter = ColoredFormatter::new(true);
        let event = LogEvent::new(Level::Info, "日志::模块", "消息 🚀 émoji");
        let output = formatter.format(&event);

        assert!(output.contains("日志::模块"));
        assert!(output.contains("消息 🚀 émoji"));
    }

    // UT-9.1-025: 超长消息格式化
    #[test]
    fn test_format_long_message() {
        let formatter = ColoredFormatter::new(true);
        let long_msg = "A".repeat(10000);
        let event = LogEvent::new(Level::Info, "test", long_msg.clone());
        let output = formatter.format(&event);

        assert!(output.contains(&long_msg));
    }
}
